home *** CD-ROM | disk | FTP | other *** search
- // midicut written by Günter Nagler 1997 (gnagler@ihm.tu-graz.ac.at)
- #include "midiio.hpp"
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- static char* version = "midicut v1.0 by Günter Nagler (" __DATE__ ")";
-
- char* input = 0;
- char* output = 0;
-
- MidiWrite* write = 0;
-
- int copychannel[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- unsigned long startms = 0;
- unsigned long endms = 0xFFFFFFFFUL;
- long startunit = -1; // will be calculated when reaching first track
- long endunit = -1;
- int quiet = 0;
-
- class MidiCut : public MidiCopy
- {
- public:
- MidiCut(char* name);
-
- virtual void track(int trackno, long length, int channel);
- virtual void time(unsigned long ticks); // delay between events
-
- virtual void meta(int what, int len, unsigned char* data);
- virtual void program(int prg, int channel);
- virtual void control(int channel, int what, int val); // general controls
- virtual void pitchbend(int channel, int val);
- virtual void noteon(int channel, int note, int vel);
- virtual void noteoff(int channel, int note, int vel);
- virtual void polyaftertouch(int channel, int note, int val);
- virtual void aftertouch(int channel, int val);
- virtual void sysex(int syslen, unsigned char* sysdata);
-
- virtual void event(int what, int len = 0, unsigned char* data = 0);
-
- virtual void error(const char* msg);
- virtual void warning(const char* msg);
-
- virtual void percent(int perc);
-
- int cutrange();
- int cutstart();
- int cutend();
- int cutrange(unsigned long ms);
- };
-
- MidiCut::MidiCut(char* name) : MidiCopy(name)
- {
- }
-
- int MidiCut::cutrange(unsigned long ms)
- {
- return (ms < startms || ms > endms);
- }
-
- int MidiCut::cutstart()
- {
- if (startunit >= 0)
- return curunit_ < startunit;
- return curms_ < startms;
- }
-
- int MidiCut::cutend()
- {
- if (endunit >= 0)
- return curunit_ >= endunit;
- return curms_ >= endms;
- }
-
- int MidiCut::cutrange()
- {
- return cutstart() || cutend();
- }
-
- void MidiCut::track(int trackno, long length, int channel)
- {
- MidiCopy::track(trackno, length, channel);
- }
-
- void MidiCut::time(unsigned long units)
- {
- unsigned long nextms, nextrest;
-
- if (startunit >= 0)
- {
- if (curunit_ + units < startunit)
- return;
- if (curunit_ < startunit)
- units -= startunit-curunit_;
- }
- else
- {
- calctime(units, nextms, nextrest);
-
- if (nextms < startms)
- return;
- startunit = calcunit(startms, 0);
- units = curunit_ + units - startunit;
- }
- if (endunit >= 0)
- {
- if (curunit_ >= endunit)
- return;
- if (curunit_ + units >= endunit)
- units = endunit - curunit_;
- }
- else
- {
- calctime(units, nextms, nextrest);
- if (curms_ <= endms && nextms >= endms)
- {
- endunit = calcunit(endms, 0);
- units = endunit - curunit_;
- }
- if (curms_ >= endms)
- return;
- }
- MidiCopy::time(units);
- }
-
- void MidiCut::meta(int what, int len, unsigned char* data)
- {
- MidiCopy::meta(what, len, data);
- }
-
- void MidiCut::program(int channel, int prg)
- {
- if (cutend() ||!copychannel[channel])
- return;
- MidiCopy::program(channel, prg);
- }
-
- void MidiCut::control(int channel, int what, int val)
- {
- if (cutend() ||!copychannel[channel])
- return;
- MidiCopy::control(channel, what, val);
- }
-
- void MidiCut::pitchbend(int channel, int val)
- {
- if (cutend() ||!copychannel[channel])
- return;
- MidiCopy::pitchbend(channel, val);
- }
-
- void MidiCut::noteon(int channel, int note, int vel)
- {
- if (cutrange() || !copychannel[channel])
- return;
- MidiCopy::noteon(channel, note, vel);
- }
-
- void MidiCut::noteoff(int channel, int note, int vel)
- {
- if (cutstart() || !copychannel[channel])
- return;
- MidiCopy::noteoff(channel, note, vel);
- }
-
- void MidiCut::polyaftertouch(int channel, int note, int val)
- {
- if (cutend() ||!copychannel[channel])
- return;
- MidiCopy::polyaftertouch(channel, note, val);
- }
-
- void MidiCut::aftertouch(int channel, int val)
- {
- if (cutend() || !copychannel[channel])
- return;
- MidiCopy::aftertouch(channel, val);
- }
-
- void MidiCut::sysex(int syslen, unsigned char* sysdata)
- {
- if (cutend())
- return;
- MidiCopy::sysex(syslen, sysdata);
- }
-
- void MidiCut::event(int what, int len, unsigned char* data)
- {
- if (cutend())
- return;
- MidiCopy::event(what, len, data);
- }
-
- void MidiCut::percent(int perc)
- {
- if (!quiet)
- fprintf(stderr, "%-3d%%\r", perc);
- }
-
- void MidiCut::error(const char* msg)
- {
- printf("Error: %s\n", msg);
- exit(1);
- }
-
- void MidiCut::warning(const char* msg)
- {
- printf("Warning: %s\n", msg);
- }
-
- void usage()
- {
- fprintf(stderr, "midicut copies a part of a midi song into a new file\n");
- fprintf(stderr, "usage: MidiCut [-q][-ch #[-#]][-from #][-till #] file.mid cutfile.mid\n");
- fprintf(stderr, "-version\tget program version\n");
- fprintf(stderr, "-q\tbe quiet\n");
- fprintf(stderr, "-channel c[-d]\tcopy only selected channels c..d (1-16) to output\n");
- fprintf(stderr, "-from #\tstart cut at second # (default: 0)\n");
- fprintf(stderr, "-end #\tend cut at second # (default: end of song)\n");
- exit(1);
- }
-
- int main(int argc, char**argv)
- {
- int changed = 0;
-
- argc--; argv++;
- while (argc > 0 && **argv == '-')
- {
- if (strncmp(*argv, "-version", 2) == 0)
- {
- fprintf(stderr, "%s\n", version);
- argc--; argv++;
- if (argc == 0)
- return 0;
- continue;
- }
- if (argc > 0 && strcmp(*argv, "-q") == 0)
- {
- quiet = 1;
- argc--; argv++;
- continue;
- }
- if (strncmp(*argv, "-channel", 2) == 0)
- {
- int firstchannel, secondchannel;
-
- argc--; argv++;
- if (argc > 0 && sscanf(*argv, "%u-%u", &firstchannel, &secondchannel) == 2)
- {
- if (firstchannel <= 0 || secondchannel > 16)
- {
- fprintf(stderr, "channel number %s out of range 1-16\n", *argv);
- firstchannel = secondchannel = -1;
- }
- else if (firstchannel > secondchannel)
- {
- fprintf(stderr, "%s: first channel number must be less than second one\n", *argv);
- firstchannel = secondchannel = -1;
- }
- argc--; argv++;
- }
- else if (argc > 0 && isdigit(**argv))
- {
- firstchannel = atoi(*argv);
- if (firstchannel <= 0 || firstchannel > 16)
- {
- fprintf(stderr, "channel number %s out of range 1-16\n", *argv);
- firstchannel = -1;
- }
- secondchannel = firstchannel;
- argc--; argv++;
- }
- else
- {
- fprintf(stderr, "option -channel expects channel number 1-16\n");
- usage();
- break;
- }
- for (int c = firstchannel; c <= secondchannel; c++)
- {
- copychannel[c-1] = 1;
- changed++;
- }
- continue;
- }
- if (strncmp(*argv, "-from", 2) == 0)
- {
- argc--; argv++;
- if (argc > 0 && isdigit(**argv))
- {
- startms = atol(*argv) * 1000; // millisec!
- argc--; argv++;
- }
- else
- fprintf(stderr, "option -from needs a time parameter (seconds)\n");
- continue;
- }
- if (strncmp(*argv, "-till", 2) == 0)
- {
- argc--; argv++;
- if (argc > 0 && isdigit(**argv))
- {
- endms = atol(*argv) * 1000; // millisec!
- argc--; argv++;
- }
- else
- fprintf(stderr, "option -till needs a time parameter (seconds)\n");
- continue;
- }
- fprintf(stderr, "invalid option %s\n", *argv);
- argc--; argv++;
- usage();
- }
- if (argc < 2)
- usage();
-
- input = argv[0];
- output = argv[1];
- if (strcmp(input, output) == 0)
- {
- fprintf(stderr, "cannot convert midi to same file\n");
- return 1;
- }
- MidiCut midi(input);
- if (!midi.getf())
- {
- perror(input);
- return 1;
- }
- write = new MidiWrite(output);
- if (!write)
- {
- fprintf(stderr, "out of memory\n");
- return 1;
- }
- if (!write->getf())
- {
- perror(output);
- return 1;
- }
- argc--; argv++;
-
- if (!changed)
- {
- // default: all channels
- for (int c = 0; c < 16; c++)
- copychannel[c] = 1;
- }
-
- midi.setoutput(write);
-
- midi.options_ = OPTION_NOCONTROLS+OPTION_NOSYSEVENTS;
- if (!midi.run())
- fprintf(stderr, "%s: midi read error at %04lX\n", input, midi.getpos());
-
- delete write;
-
- // fprintf(stderr, "cut units %ld-%ld\n", startunit, endunit);
- return 0;
- }
-